#ifndef G3_CONTROLLER_H
#define G3_CONTROLLER_H

#include "math/m_quaternion.h"
#include "singleton.h"
#include <vector>
#include <string>
#include <map>

using std::vector;
using std::map;
using std::pair;
using std::string;

namespace G3 {

	enum CONTROLLER_TYPE {
		CT_BASE = 0,
		CT_ROTATION = 1,
		CT_TRANSLATION = 2,
		CT_SCALE = 3,
		CT_COLOR = 2
	};

	class CONTROLLER {
		public:
			CONTROLLER ();
			virtual ~CONTROLLER () {}

		string name;

		bool enabled;

		MATRIX4x4F matrix;

		CONTROLLER& operator=(const CONTROLLER &c);

//==============================================================================
// Updates transformation controller
//==============================================================================
		virtual void Update (double elapsedTime = 1.0);

//==============================================================================
// Gets Controller type
//==============================================================================
		virtual CONTROLLER_TYPE GetType ();
	};

	class ROTATION_CTRL: public CONTROLLER {
		public:
			ROTATION_CTRL ();

		G3::VEC3F angles;
		QUATERNIONF rotation;

		ROTATION_CTRL& operator=(const ROTATION_CTRL &c);

		void SetRotation (float angle, G3::VEC3F axis);

		void Update (double elapsedTime = 1.0);

		CONTROLLER_TYPE GetType ();
	};

	class TRANSLATION_CTRL: public CONTROLLER {
		public:
			TRANSLATION_CTRL ();

		G3::VEC3F translation;

		TRANSLATION_CTRL& operator=(const TRANSLATION_CTRL &c);

		void SetTranslation (G3::VEC3F axis);

		void Update (double elapsedTime = 1.0);

		CONTROLLER_TYPE GetType ();
	};

	class SCALE_CTRL: public CONTROLLER {
		public:
			SCALE_CTRL ();

		G3::VEC3F scale;

		SCALE_CTRL& operator=(const SCALE_CTRL &c);

		void SetScale (G3::VEC3F axis);

		void Update (double elapsedTime = 1.0);

		CONTROLLER_TYPE GetType ();
	};

    class CONTROLLER_MGR: public SINGLETON<CONTROLLER_MGR> {
        public:
            CONTROLLER_MGR ();
            ~CONTROLLER_MGR ();

            map<int, CONTROLLER> controller_map;
            int num_controllers_total;

        //==============================================================================
        // Adds a controller
        //==============================================================================
            int AddController (CONTROLLER controller);

        //==============================================================================
        // Removes a controller
        //==============================================================================
            bool RemoveController (int cID);

        //==============================================================================
        // Gets a controller
        //==============================================================================
            CONTROLLER *GetController (int cID);

            void UpdateControllers (double elapsedTime = 1.0);
    };

    extern CONTROLLER_MGR ControllerManager;
}

#endif
